<?php

!defined('IN_VIFRAME') && die('Access Denied.');

class Vi {

	protected static
		$_FilePrefix         = array(),
		$_FileSuffix         = '',
		$_Aliases            = array(),
		$_Imported           = array();

	protected static
		$_FilePrefixFilters  = '';
	
	public static function getVersion() {
		return VI_VERSION;
	}
	
	public static function getRelease() {
		return VI_RELEASE;
	}
	
	public static function getPowered() {
		return 'Powered By ViFramework [Version '.VI_VERSION.' Released On '.VI_RELEASE.']';
	}
	
	public static function getRoot() {
		return VI_ROOT;
	}
	
	public static function import($key, $filterAlias = VI_SYSTEM_FILTERALIAS) {
		if (is_array($key)) {
			$columns = $key;
		} else {
			$columns = explode(';', $key);
		}
		
		foreach ($columns as $column) {
			$column = trim($column);
			$temp   = rtrim($column, '.*');
			if ($temp === $column) {
				$files = self::getImportFilesByPath($column, $filterAlias);
				
				if (!self::_importFiles($files)) return false;
			} else {
				$files = self::getImportFilesByDir($temp, $filterAlias);
				
				if (!self::_importFiles($files)) return false; 
			}
		}
		
		return true;
	}
	
	protected static function _importFiles($files) {
		foreach ($files as $file) {
			if (!self::isImported($file)) {
				if (is_file($file)) {
					include($file);
				} else {
					return false;
				}
				self::$_Imported[$file] = true;
			}
		}
		
		return true;
	}
	
	public static function isImported($path) {
		return (isset(self::$_Imported[$path]) && self::$_Imported[$path]);
	}
	
	public static function getImportedFiles() {
		return array_keys(self::$_Imported);
	}
	
	public static function getImportFilesByPath($key, $filterAlias = VI_SYSTEM_FILTERALIAS) {
		if (false === strpos($key, ':')) {
			$key = VI_SYSTEM_IMPORTPATHFILTER.$key;
		}
		list($type, $files) = explode(':', $key);
		$type               = trim($type);
		$files              = explode(',', $files); 
		
		foreach ($files as $cntKey => $file) {
			$file = trim($file);
			if ($filterAlias) {
				$aliases    = explode('.', $file);
				$aliasCount = count($aliases);
				$cntAlias   = '';
				$found      = -1;
				$path       = '';
				
				for ($i = 0;$i < $aliasCount;++$i) {
					$cntAlias .= $aliases[$i];
					if (isset(self::$_Aliases[$cntAlias])) {
						$path  = self::$_Aliases[$cntAlias];
						$found = $i;
					}
				}
				
				if ($found < $aliasCount - 2) {
					for ($i = $found + 1;$i < $aliasCount - 1;++$i) {
						$path .= $aliases[$i].DIRECTORY_SEPARATOR;
					}
				}
				
				if ($found < $aliasCount - 1) {
					$path .= self::getFilePrefix($type).$aliases[$aliasCount - 1]
							.self::$_FileSuffix;
				}
			} else {
				$dirnames = explode('.', $file);
				$filename = array_pop($dirnames);
				$path     = VI_ROOT.implode(DIRECTORY_SEPARATOR, $dirnames).DIRECTORY_SEPARATOR;
				$path    .= self::getFilePrefix($type).$filename.self::$_FileSuffix;
			}
			
			$files[$cntKey] = $path;
		}
		
		return $files;
	}
	
	public static function getImportFilesByDir($key, $filterAlias = VI_SYSTEM_FILTERALIAS) {
		if (false === strpos($key, ':')) {
			$key = VI_SYSTEM_IMPORTDIRFILTER.$key;
		}
		list($type, $dir)         = explode(':', $key);
		$type                     = trim($type);
		self::$_FilePrefixFilters = $type.',';
		
		if ($filterAlias) {
			$aliases    = explode('.', trim($dir));
			$aliasCount = count($aliases);
			$cntAlias   = '';
			$found      = -1;
			$path       = '';
			
			for ($i = 0;$i < $aliasCount;++$i) {
				$cntAlias .= $aliases[$i];
				if (isset(self::$_Aliases[$cntAlias])) {
					$path  = self::$_Aliases[$cntAlias];
					$found = $i;
				}
			}
	
			if ($found < $aliasCount - 1) {
				for ($i = $found + 1;$i < $aliasCount;++$i) {
					$path .= $aliases[$i].DIRECTORY_SEPARATOR;
				}
			}
		} else {
			$path = VI_ROOT.str_replace('.', DIRECTORY_SEPARATOR, trim($file));
		}

		return self::_walkImportFilesByDir($path);
	}
	
	protected static function _walkImportFilesByDir($dir) {
		if (!is_dir($dir)) return array();
		
		$files = array();
		$handle = opendir($dir);
		if($handle) {
			while(false !== ($file = readdir($handle))) {
				if ('.' != $file && '..' != $file) {
					$path = "$dir$file";
					if(is_file($path)) {
						$pos     = strpos($file, '.');
						$type    = substr($file, 0, $pos);
						if ('All,' === self::$_FilePrefixFilters
								|| false !== strpos(self::$_FilePrefixFilters, "$type,")) {

							$files[] = self::formatPath($path);
						}
					} else {
						$files = array_merge($files, self::_walkImportDir($path.'/'));
					}
				}
 			}
 			closedir($handle);
		}
		
		return $files;
	}
	
	public static function checkClassExist($key, $msg = VI_SYSTEM_CLASSEXIST) {
		$classes = explode(',', $key);
		foreach ($classes as $class) {
			$class = trim($class);
			if (!class_exists($class) && !interface_exists($class)) {
				Vi::message($msg, array('{Class}' => $class), true);
			}
		}
	}
	
	public static function getFilePrefix($type) {
		return (isset(self::$_FilePrefix[$type])
				? self::$_FilePrefix[$type] : "$type.");
	}
	
	public static function setFilePrefix($type, $fix = null) {
		if (is_array($type)) {
			self::$_FilePrefix = $type + self::$_FilePrefix;
		} elseif (is_null($fix)) {
			unset(self::$_FilePrefix[$type]);
		} else {
			self::$_FilePrefix[$type] = (string) $fix;
		}
		
		return true;
	}
	
	public static function getFileSuffix() {
		return self::$_FileSuffix;
	}
	
	public static function setFileSuffix($fix) {
		self::$_FileSuffix = (string) $fix;
		
		return true;
	}
	
	public static function getAlias($key) {
		return (isset(self::$_Aliases[$key])
				? self::$_Aliases[$key] : false);
	}
	
	public static function setAlias($key, $alias = null) {
		if (is_array($key)) {
			self::$_Aliases = $key + self::$_Aliases;
		} elseif (is_null($alias)) {
			unset(self::$_Aliases[$key]);
		} else {
			self::$_Aliases[$key] = (string) $alias;
		}

		return true;
	}
	public static function formatPath($path) {
		return str_replace(array('\\', '/'), DIRECTORY_SEPARATOR, $path);
	}
	
	public static function message($msg, $value = array(), $style = '', $die = false) {
		if (is_bool($style)) {
			$die   = $style;
			$style = '';
		}
		if (is_bool($value)) {
			$die   = $value;
			$value = array();
		}
		
		$msg = str_replace(array_keys($value), array_values($value), $msg);
		
		if (class_exists('OTinyMessage')) {
			$tinyMsg = new OTinyMessage($msg, $style);
			$tinyMsg->flush($die);
		} else {
			echo($msg);
			if ($die) die();
		}
		
		return true;
	}
	
	public static function handleException($exception) {
		if (class_exists('TException') && ($exception instanceof TException) && class_exists('OSystemMessage')) {
			$sysMsg = new OSystemMessage('ViFramework Exception');
			$sysMsg->appendProperty('Key', $exception->getKey(), 12, 1)
			       ->appendProperty('File', $exception->getFile())
			       ->appendProperty('Line', $exception->getLine())
			       ->appendTrace('Trace', $exception->getTrace(), 12, 1)
			       ->appendExport('Detail', $exception->getDetail(), 12, 1)
			       ->appendSeparator()
			       ->flush(true);
		} else {
			die($exception->getTraceAsString());
		}
		
		return true;
	}
	
	public static function handleError($no, $string, $file, $line) {
		if (class_exists('OSystemMessage')) {
			$sysMsg = new OSystemMessage('ViFramework Error');
			$sysMsg->appendProperty('No', $no, 7, 1)
				   ->appendProperty('String', $string)
				   ->appendProperty('File', $file)
				   ->appendProperty('Line', $line)
				   ->appendSeparator()
				   ->flush(true);
		} else {
			die("Error $no : $string [Line $line In $file]");
		}

		return true;
	}
}
